Set up

suppressPackageStartupMessages({
  library(tidyverse)
})

Directories and File Inputs/Outputs

# Detect the ".git" folder -- this will be in the project root directory
# Use this as the root directory to ensure proper sourcing of functions 
# no matter where this is called from
root_dir <- rprojroot::find_root(rprojroot::has_dir(".git"))
analysis_dir <- file.path(root_dir, "analyses", "tmb-vaf-longitudinal")
results_dir <- file.path(analysis_dir, "results")
input_dir <- file.path(analysis_dir, "input")
files_dir <- file.path(root_dir, "analyses", "sample-distribution-analysis", "results")

# Input files
pbta_file <- file.path(files_dir, "pbta.tsv") # file from add-sample-distribution module
genomic_paired_file <- file.path(files_dir, "genomic_assays_matched_time_points.tsv")
tmb_vaf_file <- file.path(results_dir, "tmb_vaf_genomic.tsv")
palette_file <- file.path(root_dir, "figures", "palettes", "oncoprint_color_palette.tsv")

# File path to plot directory
plots_dir <-
  file.path(analysis_dir, "plots")
if (!dir.exists(plots_dir)) {
  dir.create(plots_dir)
}

source(paste0(root_dir, "/figures/scripts/theme.R"))

Read in data and process

# Let's count #samples per cancer groups and timepoints.
# We will use the cg_id col that indicates cancer type as identified at the first diagnostic sample
timepoint_cg_n_df <- df %>% 
  count(cg_id, tumor_descriptor) %>% 
  dplyr::mutate(tumor_descriptor_cg_n = glue::glue("{cg_id}_{tumor_descriptor}  (N={n})")) %>% 
  dplyr::rename(timepoint_cg_n = n) 

# Let's count #samples per cancer groups and timepoints 
timepoint_cgGFAC_n_df <- df %>% 
  count(cgGFAC, td_cgGFAC) %>% 
  dplyr::mutate(tumor_descriptor_cgGFAC_n = glue::glue("{cgGFAC}_{td_cgGFAC}  (N={n})")) %>% 
  dplyr::rename(timepoint_cgGFAC_n = n) 

# Create df to use for plots
df_plot <- df %>% 
  left_join(timepoint_cg_n_df, by = c("tumor_descriptor", "cg_id")) %>%
  left_join(timepoint_cgGFAC_n_df, by = c("td_cgGFAC", "cgGFAC")) %>% 
  filter(!timepoint_cg_n <= 2,
         !timepoint_cgGFAC_n <= 2,
         !cg_id == "NA") %>% 
  mutate(tumor_descriptor = factor(tumor_descriptor),
         tumor_descriptor = fct_relevel(tumor_descriptor, timepoints))
Warning: There was 1 warning in `mutate()`.
ℹ In argument: `tumor_descriptor = fct_relevel(tumor_descriptor, timepoints)`.
Caused by warning:
! 1 unknown level in `f`: Unavailable

Define parameters for plots

# Read color palette
palette_df <- readr::read_tsv(palette_file, guess_max = 100000, show_col_types = FALSE) 

# Define and order palette
palette <- palette_df$hex_codes
names(palette) <- palette_df$Variant_Classification
Warning: Unknown or uninitialised column: `Variant_Classification`.
# Define label for plots
Alteration_type <- df_plot$Variant_Classification

# Define ylim
ylim <- max(df_plot$log10_tmb)

What type of alterations we observe per tumor descriptor?

# Create bxp
print(ggpubr::ggboxplot(df_plot, 
                        x = "tumor_descriptor", 
                        y = "log10_tmb", 
                        color = "Variant_Classification",
                        palette = palette) +
        theme_Publication() + 
        scale_y_continuous(limits = c(0, ylim)) +
        xlab("Timepoint") +
        theme(axis.text.x = element_text(angle = 90)))


# Save the plot
ggsave(filename = "Alteration_type_timepoints.pdf", 
       path = plots_dir, 
       width = 15, 
       height = 8, 
       device = "pdf", 
       useDingbats = FALSE)

What type of alterations we observe per tumor descriptor in each cancer group?

# Create bxp
print(ggpubr::ggboxplot(df_plot, 
                        x = "tumor_descriptor", 
                        y = "log10_tmb", 
                        color = "Variant_Classification",
                        palette = palette) +
        facet_wrap(~cg_id) +
        theme_Publication() + 
        xlab("Timepoint") +
        scale_y_continuous(limits = c(0, ylim)) +
        theme(axis.text.x = element_text(angle = 90)))


# Save the plot
ggsave(filename = "Alteration_type_cg_id.pdf", 
       path = plots_dir, 
       width = 25, 
       height = 18, 
       device = "pdf", 
       useDingbats = FALSE)

What type of alterations we observe per tumor descriptor in each cancer group defined by cgGFAC?

df_plot_cgGFAC <- df_plot %>% 
  arrange(tumor_descriptor_cgGFAC_n)

# Create bxp
print(ggpubr::ggboxplot(df_plot_cgGFAC, 
                        x = "tumor_descriptor_cgGFAC_n", 
                        y = "log10_tmb", 
                        color = "Variant_Classification",
                        palette = palette) +
        theme_Publication() + 
        xlab("Timepoint") +
        scale_y_continuous(limits = c(0, ylim)) +
        theme(axis.text.x = element_text(angle = 90)))


# Save the plot
ggsave(filename = "Alteration_type_cgGFAC.pdf", 
       path = plots_dir, 
       width = 14, 
       height = 8, 
       device = "pdf", 
       useDingbats = FALSE)
cgGFAC_id <- as.character(unique(df_plot_cgGFAC$cgGFAC))
cgGFAC_id
[1] "ATRT"  "DMG"   "HGG"   "LGG"   "Other"
# Loop through variable
for (i in seq_along(cgGFAC_id)){
  print(i)
  df_sub <- df_plot_cgGFAC %>%
      filter(cgGFAC == cgGFAC_id[i])

  
   # Create bxp
  print(ggpubr::ggboxplot(df_sub, 
                        x = "tumor_descriptor_cgGFAC_n", 
                        y = "log10_tmb", 
                        color = "Variant_Classification",
                        palette = palette) +
        theme_Publication() + 
        labs(title = paste(cgGFAC_id[i])) +
        scale_y_continuous(limits = c(0, ylim)) +
        theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1)))
}
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5

What type of alterations we observe per tumor descriptor in each cancer group (add _n))?

cg <- as.character(unique(df_plot$cg_id))
cg
 [1] "Embryonal tumor with multilayer rosettes" "Low-grade glioma"                        
 [3] "Ependymoma"                               "Medulloblastoma"                         
 [5] "Atypical Teratoid Rhabdoid Tumor"         "Diffuse midline glioma"                  
 [7] "High-grade glioma"                        "Ganglioglioma"                           
 [9] "Meningioma"                               "Pilocytic astrocytoma"                   
[11] "CNS Embryonal tumor"                      "Neuroblastoma"                           
[13] "Schwannoma"                               "Chordoma"                                
[15] "Malignant peripheral nerve sheath tumor"  "Choroid plexus carcinoma"                
[17] "Adamantinomatous Craniopharyngioma"       "Dysembryoplastic neuroepithelial tumor"  
[19] "Ewing sarcoma"                            "Rosai-Dorfman disease"                   
[21] "Neurofibroma/Plexiform"                   "Glial-neuronal tumor"                    
[23] "Hemangioblastoma"                         "Craniopharyngioma"                       
# Loop through variable
for (i in seq_along(cg)){
  print(i)
  df_sub <- df_plot %>%
      filter(cg_id == cg[i])
  
  # Create bxp
  print(ggpubr::ggboxplot(df_sub, 
                        x = "tumor_descriptor_cg_n", 
                        y = "log10_tmb", 
                        color = "Variant_Classification",
                        palette = palette) +
        theme_Publication() + 
        xlab("Timepoint") +
        labs(title = paste(cg[i])) +
        scale_y_continuous(limits = c(0, ylim)) +
        theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1)))
}
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
[1] 6
[1] 7
[1] 8
[1] 9
[1] 10
[1] 11
[1] 12
[1] 13
[1] 14
[1] 15
[1] 16
[1] 17
[1] 18
[1] 19
[1] 20
[1] 21
[1] 22
[1] 23
[1] 24

What type of alterations we observe per tumor descriptor in each cancer group and timepoint model?

df_plot <- df_plot %>%
      filter(!is.na(timepoints_models))

tm <- as.character(unique(df_plot$timepoints_models))
tm
[1] "Dx-Rec"     "Dx-Pro"     "Rec-SM"     "Pro-Rec"    "Dx-SM"      "Dx-Pro-Rec"
# Loop through variable
for (i in seq_along(tm)){
  print(i)
  df_sub <- df_plot %>%
      filter(timepoints_models == tm[i],
             !is.na(timepoints_models))
  
  # Create bxp
  print(ggpubr::ggboxplot(df_sub, 
                        x = "tumor_descriptor", 
                        y = "tmb", 
                        color = "Variant_Classification",
                        palette = palette) +
        facet_wrap(~cg_id) +
        theme_Publication() +
        ylab("TMB") +
        xlab("Timepoint") +
        scale_y_continuous(limits = c(0, ylim)) +
        theme(axis.text.x = element_text(angle = 90)))
}
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
[1] 6

LS0tCnRpdGxlOiAiQ2xhc3NpZmljYXRpb24gb2YgVmFyaWFudHMgYWNyb3NzIHBhaXJlZCBsb25naXR1ZGluYWwgc2FtcGxlcyBpbiB0aGUgUEJUQSBDb2hvcnQiCmF1dGhvcjogJ0FudG9uaWEgQ2hyb25pIDxjaHJvbmlhQGNob3AuZWR1PiBmb3IgRDNCJwpkYXRlOiAiMjAyMyIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IFRSVUUKICAgIHRvY19mbG9hdDogVFJVRQotLS0KCiMgU2V0IHVwCmBgYHtyIGxvYWQtbGlicmFyeX0Kc3VwcHJlc3NQYWNrYWdlU3RhcnR1cE1lc3NhZ2VzKHsKICBsaWJyYXJ5KHRpZHl2ZXJzZSkKfSkKYGBgCgojIERpcmVjdG9yaWVzIGFuZCBGaWxlIElucHV0cy9PdXRwdXRzCmBgYHtyIHNldC1kaXItYW5kLWZpbGUtbmFtZXN9CiMgRGV0ZWN0IHRoZSAiLmdpdCIgZm9sZGVyIC0tIHRoaXMgd2lsbCBiZSBpbiB0aGUgcHJvamVjdCByb290IGRpcmVjdG9yeQojIFVzZSB0aGlzIGFzIHRoZSByb290IGRpcmVjdG9yeSB0byBlbnN1cmUgcHJvcGVyIHNvdXJjaW5nIG9mIGZ1bmN0aW9ucyAKIyBubyBtYXR0ZXIgd2hlcmUgdGhpcyBpcyBjYWxsZWQgZnJvbQpyb290X2RpciA8LSBycHJvanJvb3Q6OmZpbmRfcm9vdChycHJvanJvb3Q6Omhhc19kaXIoIi5naXQiKSkKYW5hbHlzaXNfZGlyIDwtIGZpbGUucGF0aChyb290X2RpciwgImFuYWx5c2VzIiwgInRtYi12YWYtbG9uZ2l0dWRpbmFsIikKcmVzdWx0c19kaXIgPC0gZmlsZS5wYXRoKGFuYWx5c2lzX2RpciwgInJlc3VsdHMiKQppbnB1dF9kaXIgPC0gZmlsZS5wYXRoKGFuYWx5c2lzX2RpciwgImlucHV0IikKZmlsZXNfZGlyIDwtIGZpbGUucGF0aChyb290X2RpciwgImFuYWx5c2VzIiwgInNhbXBsZS1kaXN0cmlidXRpb24tYW5hbHlzaXMiLCAicmVzdWx0cyIpCgojIElucHV0IGZpbGVzCnBidGFfZmlsZSA8LSBmaWxlLnBhdGgoZmlsZXNfZGlyLCAicGJ0YS50c3YiKSAjIGZpbGUgZnJvbSBhZGQtc2FtcGxlLWRpc3RyaWJ1dGlvbiBtb2R1bGUKZ2Vub21pY19wYWlyZWRfZmlsZSA8LSBmaWxlLnBhdGgoZmlsZXNfZGlyLCAiZ2Vub21pY19hc3NheXNfbWF0Y2hlZF90aW1lX3BvaW50cy50c3YiKQp0bWJfdmFmX2ZpbGUgPC0gZmlsZS5wYXRoKHJlc3VsdHNfZGlyLCAidG1iX3ZhZl9nZW5vbWljLnRzdiIpCnBhbGV0dGVfZmlsZSA8LSBmaWxlLnBhdGgocm9vdF9kaXIsICJmaWd1cmVzIiwgInBhbGV0dGVzIiwgIm9uY29wcmludF9jb2xvcl9wYWxldHRlLnRzdiIpCgojIEZpbGUgcGF0aCB0byBwbG90IGRpcmVjdG9yeQpwbG90c19kaXIgPC0KICBmaWxlLnBhdGgoYW5hbHlzaXNfZGlyLCAicGxvdHMiKQppZiAoIWRpci5leGlzdHMocGxvdHNfZGlyKSkgewogIGRpci5jcmVhdGUocGxvdHNfZGlyKQp9Cgpzb3VyY2UocGFzdGUwKHJvb3RfZGlyLCAiL2ZpZ3VyZXMvc2NyaXB0cy90aGVtZS5SIikpCmBgYAoKIyBSZWFkIGluIGRhdGEgYW5kIHByb2Nlc3MKCmBgYHtyIGxvYWQtcHJvY2Vzcy1pbnB1dHN9CnBidGFfZGYgPC0gcmVhZHI6OnJlYWRfdHN2KHBidGFfZmlsZSwgZ3Vlc3NfbWF4ID0gMTAwMDAwLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKSAlPiUgCiAgc2VsZWN0KEtpZHNfRmlyc3RfUGFydGljaXBhbnRfSUQsIEtpZHNfRmlyc3RfQmlvc3BlY2ltZW5fSUQsIGNnX211bHRpcGxlLCBjZ19pZCwgY2dHRkFDLCB0dW1vcl9kZXNjcmlwdG9yKQoKdG1iX3ZhZl9kZiA8LSByZWFkcjo6cmVhZF90c3YodG1iX3ZhZl9maWxlLCBndWVzc19tYXggPSAxMDAwMDAsIHNob3dfY29sX3R5cGVzID0gRkFMU0UpICU+JSAKICBmaWx0ZXIoIXRtYiA+PSAxMCkgJT4lIAogIHNlbGVjdChLaWRzX0ZpcnN0X0Jpb3NwZWNpbWVuX0lELCBWYXJpYW50X0NsYXNzaWZpY2F0aW9uLCBnZW5lX3Byb3RlaW4sIG11dGF0aW9uX2NvdW50LAlyZWdpb25fc2l6ZSwgdG1iLCBWQUYpCgpnZW5vbWljX3BhaXJlZF9kZiA8LSByZWFkcjo6cmVhZF90c3YoZ2Vub21pY19wYWlyZWRfZmlsZSwgZ3Vlc3NfbWF4ID0gMTAwMDAwLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKSAlPiUKICBsZWZ0X2pvaW4ocGJ0YV9kZiwgYnkgPSBjKCJLaWRzX0ZpcnN0X1BhcnRpY2lwYW50X0lEIikpICU+JSAKICBsZWZ0X2pvaW4odG1iX3ZhZl9kZiwgYnkgPSBjKCJLaWRzX0ZpcnN0X0Jpb3NwZWNpbWVuX0lEIikpICU+JQogIGZpbHRlcighaXMubmEodG1iKSkKCiMgQXR0ZW50aW9uIGFzIHNvbWUgYnMgc3BlY2ltZW4gbWlnaHQgbm90IGhhdmUgVE1CIQojIElmIHRoYXQgaGFwcGVucywgd2Ugd2lsbCBlbmQgdXAgd2l0aCBzYW1wbGVzIGxhY2tpbmcgdGltZXBvaW50cy4KCiMgV2hpY2ggcGF0aWVudCBzYW1wbGVzIGRvbid0IGhhdmUgVE1CPwojIGdlbm9taWNfcGFpcmVkX2RmICU+JSAKIyAgZmlsdGVyKGlzLm5hKHRtYikpICU+JSAKIyAgdW5pcXVlKCkgJT4lIAojICByZWd1bGFydGFibGUoKSAlPiUKIyAgZm9udHNpemUoc2l6ZSA9IDEyLCBwYXJ0ID0gImFsbCIpCgpkZXNjcmlwdG9yc19kZiA8LSBnZW5vbWljX3BhaXJlZF9kZiAlPiUKICBncm91cF9ieShLaWRzX0ZpcnN0X1BhcnRpY2lwYW50X0lEKSAlPiUKICBzdW1tYXJpemUoZGVzY3JpcHRvcnMgPSBwYXN0ZShzb3J0KHR1bW9yX2Rlc2NyaXB0b3IpLCBjb2xsYXBzZSA9ICIsICIpLCkgCgojIFZlY3RvciB0byBvcmRlciB0aW1lcG9pbnRzCnRpbWVwb2ludHMgPC0gYygiRGlhZ25vc2lzIiwgIlByb2dyZXNzaXZlIiwgIlJlY3VycmVuY2UiLCAiRGVjZWFzZWQiLCAiU2Vjb25kIE1hbGlnbmFuY3kiLCAiVW5hdmFpbGFibGUiKQoKZGYgPC0gZ2Vub21pY19wYWlyZWRfZGYgJT4lIAogIGxlZnRfam9pbihkZXNjcmlwdG9yc19kZiwgYnkgPSBjKCJLaWRzX0ZpcnN0X1BhcnRpY2lwYW50X0lEIiwgImRlc2NyaXB0b3JzIikpICU+JSAKICBtdXRhdGUodGRfY2dHRkFDID0gY2FzZV93aGVuKGdyZXBsKCJEZWNlYXNlZCIsIHR1bW9yX2Rlc2NyaXB0b3IpIH4gInhEZWNlYXNlZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gdHVtb3JfZGVzY3JpcHRvciksCiAgICAgICAgIGxvZzEwX3RtYiA9IGFicyhsb2cxMCh0bWIpKSkKCiMgTGV0J3MgY291bnQgI3NhbXBsZXMgcGVyIGNhbmNlciBncm91cHMgYW5kIHRpbWVwb2ludHMuCiMgV2Ugd2lsbCB1c2UgdGhlIGNnX2lkIGNvbCB0aGF0IGluZGljYXRlcyBjYW5jZXIgdHlwZSBhcyBpZGVudGlmaWVkIGF0IHRoZSBmaXJzdCBkaWFnbm9zdGljIHNhbXBsZQp0aW1lcG9pbnRfY2dfbl9kZiA8LSBkZiAlPiUgCiAgY291bnQoY2dfaWQsIHR1bW9yX2Rlc2NyaXB0b3IpICU+JSAKICBkcGx5cjo6bXV0YXRlKHR1bW9yX2Rlc2NyaXB0b3JfY2dfbiA9IGdsdWU6OmdsdWUoIntjZ19pZH1fe3R1bW9yX2Rlc2NyaXB0b3J9ICAoTj17bn0pIikpICU+JSAKICBkcGx5cjo6cmVuYW1lKHRpbWVwb2ludF9jZ19uID0gbikgCgojIExldCdzIGNvdW50ICNzYW1wbGVzIHBlciBjYW5jZXIgZ3JvdXBzIGFuZCB0aW1lcG9pbnRzIAp0aW1lcG9pbnRfY2dHRkFDX25fZGYgPC0gZGYgJT4lIAogIGNvdW50KGNnR0ZBQywgdGRfY2dHRkFDKSAlPiUgCiAgZHBseXI6Om11dGF0ZSh0dW1vcl9kZXNjcmlwdG9yX2NnR0ZBQ19uID0gZ2x1ZTo6Z2x1ZSgie2NnR0ZBQ31fe3RkX2NnR0ZBQ30gIChOPXtufSkiKSkgJT4lIAogIGRwbHlyOjpyZW5hbWUodGltZXBvaW50X2NnR0ZBQ19uID0gbikgCgojIENyZWF0ZSBkZiB0byB1c2UgZm9yIHBsb3RzCmRmX3Bsb3QgPC0gZGYgJT4lIAogIGxlZnRfam9pbih0aW1lcG9pbnRfY2dfbl9kZiwgYnkgPSBjKCJ0dW1vcl9kZXNjcmlwdG9yIiwgImNnX2lkIikpICU+JQogIGxlZnRfam9pbih0aW1lcG9pbnRfY2dHRkFDX25fZGYsIGJ5ID0gYygidGRfY2dHRkFDIiwgImNnR0ZBQyIpKSAlPiUgCiAgZmlsdGVyKCF0aW1lcG9pbnRfY2dfbiA8PSAyLAogICAgICAgICAhdGltZXBvaW50X2NnR0ZBQ19uIDw9IDIsCiAgICAgICAgICFjZ19pZCA9PSAiTkEiKSAlPiUgCiAgbXV0YXRlKHR1bW9yX2Rlc2NyaXB0b3IgPSBmYWN0b3IodHVtb3JfZGVzY3JpcHRvciksCiAgICAgICAgIHR1bW9yX2Rlc2NyaXB0b3IgPSBmY3RfcmVsZXZlbCh0dW1vcl9kZXNjcmlwdG9yLCB0aW1lcG9pbnRzKSkKYGBgIAoKIyBEZWZpbmUgcGFyYW1ldGVycyBmb3IgcGxvdHMKCmBgYHtyIGRlZmluZS1wYXJhbWV0ZXJzLWZvci1wbG90c30KIyBSZWFkIGNvbG9yIHBhbGV0dGUKcGFsZXR0ZV9kZiA8LSByZWFkcjo6cmVhZF90c3YocGFsZXR0ZV9maWxlLCBndWVzc19tYXggPSAxMDAwMDAsIHNob3dfY29sX3R5cGVzID0gRkFMU0UpIAoKIyBEZWZpbmUgYW5kIG9yZGVyIHBhbGV0dGUKcGFsZXR0ZSA8LSBwYWxldHRlX2RmJGhleF9jb2RlcwpuYW1lcyhwYWxldHRlKSA8LSBwYWxldHRlX2RmJFZhcmlhbnRfQ2xhc3NpZmljYXRpb24KCiMgRGVmaW5lIGxhYmVsIGZvciBwbG90cwpBbHRlcmF0aW9uX3R5cGUgPC0gZGZfcGxvdCRWYXJpYW50X0NsYXNzaWZpY2F0aW9uCgojIERlZmluZSB5bGltCnlsaW0gPC0gbWF4KGRmX3Bsb3QkbG9nMTBfdG1iKQpgYGAKCiMgV2hhdCB0eXBlIG9mIGFsdGVyYXRpb25zIHdlIG9ic2VydmUgcGVyIHR1bW9yIGRlc2NyaXB0b3I/CgpgYGB7ciBwbG90LXRpbWVwb2ludCwgZmlnLndpZHRoID0gMTUsIGZpZy5oZWlnaHQgPSA4LCBmaWcuZnVsbHdpZHRoID0gVFJVRX0KIyBDcmVhdGUgYnhwCnByaW50KGdncHVicjo6Z2dib3hwbG90KGRmX3Bsb3QsIAogICAgICAgICAgICAgICAgICAgICAgICB4ID0gInR1bW9yX2Rlc2NyaXB0b3IiLCAKICAgICAgICAgICAgICAgICAgICAgICAgeSA9ICJsb2cxMF90bWIiLCAKICAgICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAiVmFyaWFudF9DbGFzc2lmaWNhdGlvbiIsCiAgICAgICAgICAgICAgICAgICAgICAgIHBhbGV0dGUgPSBwYWxldHRlKSArCiAgICAgICAgdGhlbWVfUHVibGljYXRpb24oKSArIAogICAgICAgIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIHlsaW0pKSArCiAgICAgICAgeGxhYigiVGltZXBvaW50IikgKwogICAgICAgIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApKSkKCiMgU2F2ZSB0aGUgcGxvdApnZ3NhdmUoZmlsZW5hbWUgPSAiQWx0ZXJhdGlvbl90eXBlX3RpbWVwb2ludHMucGRmIiwgCiAgICAgICBwYXRoID0gcGxvdHNfZGlyLCAKICAgICAgIHdpZHRoID0gMTUsIAogICAgICAgaGVpZ2h0ID0gOCwgCiAgICAgICBkZXZpY2UgPSAicGRmIiwgCiAgICAgICB1c2VEaW5nYmF0cyA9IEZBTFNFKQpgYGAKCgojIFdoYXQgdHlwZSBvZiBhbHRlcmF0aW9ucyB3ZSBvYnNlcnZlIHBlciB0dW1vciBkZXNjcmlwdG9yIGluIGVhY2ggY2FuY2VyIGdyb3VwPwoKYGBge3IgcGxvdC1jZy1pZCwgZmlnLndpZHRoID0gMjUsIGZpZy5oZWlnaHQgPSAxOCwgZmlnLmZ1bGx3aWR0aCA9IFRSVUV9CiMgQ3JlYXRlIGJ4cApwcmludChnZ3B1YnI6OmdnYm94cGxvdChkZl9wbG90LCAKICAgICAgICAgICAgICAgICAgICAgICAgeCA9ICJ0dW1vcl9kZXNjcmlwdG9yIiwgCiAgICAgICAgICAgICAgICAgICAgICAgIHkgPSAibG9nMTBfdG1iIiwgCiAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gIlZhcmlhbnRfQ2xhc3NpZmljYXRpb24iLAogICAgICAgICAgICAgICAgICAgICAgICBwYWxldHRlID0gcGFsZXR0ZSkgKwogICAgICAgIGZhY2V0X3dyYXAofmNnX2lkKSArCiAgICAgICAgdGhlbWVfUHVibGljYXRpb24oKSArIAogICAgICAgIHhsYWIoIlRpbWVwb2ludCIpICsKICAgICAgICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCB5bGltKSkgKwogICAgICAgIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApKSkKCiMgU2F2ZSB0aGUgcGxvdApnZ3NhdmUoZmlsZW5hbWUgPSAiQWx0ZXJhdGlvbl90eXBlX2NnX2lkLnBkZiIsIAogICAgICAgcGF0aCA9IHBsb3RzX2RpciwgCiAgICAgICB3aWR0aCA9IDI1LCAKICAgICAgIGhlaWdodCA9IDE4LCAKICAgICAgIGRldmljZSA9ICJwZGYiLCAKICAgICAgIHVzZURpbmdiYXRzID0gRkFMU0UpCmBgYAoKCiMgV2hhdCB0eXBlIG9mIGFsdGVyYXRpb25zIHdlIG9ic2VydmUgcGVyIHR1bW9yIGRlc2NyaXB0b3IgaW4gZWFjaCBjYW5jZXIgZ3JvdXAgZGVmaW5lZCBieSBjZ0dGQUM/CgpgYGB7ciBwbG90LWNnR0ZBQy1uLCBmaWcud2lkdGggPSAxNCwgZmlnLmhlaWdodCA9IDgsIGZpZy5mdWxsd2lkdGggPSBUUlVFfQpkZl9wbG90X2NnR0ZBQyA8LSBkZl9wbG90ICU+JSAKICBhcnJhbmdlKHR1bW9yX2Rlc2NyaXB0b3JfY2dHRkFDX24pCgojIENyZWF0ZSBieHAKcHJpbnQoZ2dwdWJyOjpnZ2JveHBsb3QoZGZfcGxvdF9jZ0dGQUMsIAogICAgICAgICAgICAgICAgICAgICAgICB4ID0gInR1bW9yX2Rlc2NyaXB0b3JfY2dHRkFDX24iLCAKICAgICAgICAgICAgICAgICAgICAgICAgeSA9ICJsb2cxMF90bWIiLCAKICAgICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAiVmFyaWFudF9DbGFzc2lmaWNhdGlvbiIsCiAgICAgICAgICAgICAgICAgICAgICAgIHBhbGV0dGUgPSBwYWxldHRlKSArCiAgICAgICAgdGhlbWVfUHVibGljYXRpb24oKSArIAogICAgICAgIHhsYWIoIlRpbWVwb2ludCIpICsKICAgICAgICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCB5bGltKSkgKwogICAgICAgIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApKSkKCiMgU2F2ZSB0aGUgcGxvdApnZ3NhdmUoZmlsZW5hbWUgPSAiQWx0ZXJhdGlvbl90eXBlX2NnR0ZBQy5wZGYiLCAKICAgICAgIHBhdGggPSBwbG90c19kaXIsIAogICAgICAgd2lkdGggPSAxNCwgCiAgICAgICBoZWlnaHQgPSA4LCAKICAgICAgIGRldmljZSA9ICJwZGYiLCAKICAgICAgIHVzZURpbmdiYXRzID0gRkFMU0UpCgpgYGAKCgpgYGB7ciBwbG90LWNnR0ZBQy1uLWluZGl2aWR1YWwtcGxvdHMsIGZpZy53aWR0aCA9IDgsIGZpZy5oZWlnaHQgPSA2LCBmaWcuZnVsbHdpZHRoID0gVFJVRX0KY2dHRkFDX2lkIDwtIGFzLmNoYXJhY3Rlcih1bmlxdWUoZGZfcGxvdF9jZ0dGQUMkY2dHRkFDKSkKY2dHRkFDX2lkCgojIExvb3AgdGhyb3VnaCB2YXJpYWJsZQpmb3IgKGkgaW4gc2VxX2Fsb25nKGNnR0ZBQ19pZCkpewogIHByaW50KGkpCiAgZGZfc3ViIDwtIGRmX3Bsb3RfY2dHRkFDICU+JQogICAgICBmaWx0ZXIoY2dHRkFDID09IGNnR0ZBQ19pZFtpXSkKCiAgCiAgICMgQ3JlYXRlIGJ4cAogIHByaW50KGdncHVicjo6Z2dib3hwbG90KGRmX3N1YiwgCiAgICAgICAgICAgICAgICAgICAgICAgIHggPSAidHVtb3JfZGVzY3JpcHRvcl9jZ0dGQUNfbiIsIAogICAgICAgICAgICAgICAgICAgICAgICB5ID0gImxvZzEwX3RtYiIsIAogICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICJWYXJpYW50X0NsYXNzaWZpY2F0aW9uIiwKICAgICAgICAgICAgICAgICAgICAgICAgcGFsZXR0ZSA9IHBhbGV0dGUpICsKICAgICAgICB0aGVtZV9QdWJsaWNhdGlvbigpICsgCiAgICAgICAgbGFicyh0aXRsZSA9IHBhc3RlKGNnR0ZBQ19pZFtpXSkpICsKICAgICAgICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCB5bGltKSkgKwogICAgICAgIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIHZqdXN0ID0gMC41LCBoanVzdCA9IDEpKSkKfQpgYGAKCiMgV2hhdCB0eXBlIG9mIGFsdGVyYXRpb25zIHdlIG9ic2VydmUgcGVyIHR1bW9yIGRlc2NyaXB0b3IgaW4gZWFjaCBjYW5jZXIgZ3JvdXAgKGFkZCBfbikpPwogCmBgYHtyIHBsb3QtbiwgZmlnLndpZHRoID0gMTIsIGZpZy5oZWlnaHQgPSA4LCBmaWcuZnVsbHdpZHRoID0gVFJVRX0KY2cgPC0gYXMuY2hhcmFjdGVyKHVuaXF1ZShkZl9wbG90JGNnX2lkKSkKY2cKCiMgTG9vcCB0aHJvdWdoIHZhcmlhYmxlCmZvciAoaSBpbiBzZXFfYWxvbmcoY2cpKXsKICBwcmludChpKQogIGRmX3N1YiA8LSBkZl9wbG90ICU+JQogICAgICBmaWx0ZXIoY2dfaWQgPT0gY2dbaV0pCiAgCiAgIyBDcmVhdGUgYnhwCiAgcHJpbnQoZ2dwdWJyOjpnZ2JveHBsb3QoZGZfc3ViLCAKICAgICAgICAgICAgICAgICAgICAgICAgeCA9ICJ0dW1vcl9kZXNjcmlwdG9yX2NnX24iLCAKICAgICAgICAgICAgICAgICAgICAgICAgeSA9ICJsb2cxMF90bWIiLCAKICAgICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAiVmFyaWFudF9DbGFzc2lmaWNhdGlvbiIsCiAgICAgICAgICAgICAgICAgICAgICAgIHBhbGV0dGUgPSBwYWxldHRlKSArCiAgICAgICAgdGhlbWVfUHVibGljYXRpb24oKSArIAogICAgICAgIHhsYWIoIlRpbWVwb2ludCIpICsKICAgICAgICBsYWJzKHRpdGxlID0gcGFzdGUoY2dbaV0pKSArCiAgICAgICAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgeWxpbSkpICsKICAgICAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCB2anVzdCA9IDAuNSwgaGp1c3QgPSAxKSkpCn0KYGBgCgoKIyBXaGF0IHR5cGUgb2YgYWx0ZXJhdGlvbnMgd2Ugb2JzZXJ2ZSBwZXIgdHVtb3IgZGVzY3JpcHRvciBpbiBlYWNoIGNhbmNlciBncm91cCBhbmQgdGltZXBvaW50IG1vZGVsPwoKYGBge3IgcGxvdC10aW1lcG9pbnQtbW9kZWwsIGZpZy53aWR0aCA9IDI1LCBmaWcuaGVpZ2h0ID0gMTgsIGZpZy5mdWxsd2lkdGggPSBUUlVFfQpkZl9wbG90IDwtIGRmX3Bsb3QgJT4lCiAgICAgIGZpbHRlcighaXMubmEodGltZXBvaW50c19tb2RlbHMpKQoKdG0gPC0gYXMuY2hhcmFjdGVyKHVuaXF1ZShkZl9wbG90JHRpbWVwb2ludHNfbW9kZWxzKSkKdG0KCiMgTG9vcCB0aHJvdWdoIHZhcmlhYmxlCmZvciAoaSBpbiBzZXFfYWxvbmcodG0pKXsKICBwcmludChpKQogIGRmX3N1YiA8LSBkZl9wbG90ICU+JQogICAgICBmaWx0ZXIodGltZXBvaW50c19tb2RlbHMgPT0gdG1baV0pCiAgCiAgIyBDcmVhdGUgYnhwCiAgcHJpbnQoZ2dwdWJyOjpnZ2JveHBsb3QoZGZfc3ViLCAKICAgICAgICAgICAgICAgICAgICAgICAgeCA9ICJ0dW1vcl9kZXNjcmlwdG9yIiwgCiAgICAgICAgICAgICAgICAgICAgICAgIHkgPSAidG1iIiwgCiAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gIlZhcmlhbnRfQ2xhc3NpZmljYXRpb24iLAogICAgICAgICAgICAgICAgICAgICAgICBwYWxldHRlID0gcGFsZXR0ZSkgKwogICAgICAgIGZhY2V0X3dyYXAofmNnX2lkKSArCiAgICAgICAgdGhlbWVfUHVibGljYXRpb24oKSArCiAgICAgICAgeWxhYigiVE1CIikgKwogICAgICAgIHhsYWIoIlRpbWVwb2ludCIpICsKICAgICAgICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCB5bGltKSkgKwogICAgICAgIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApKSkKfQpgYGAKCgpgYGB7ciBlY2hvPVRSVUV9CnNlc3Npb25JbmZvKCkKYGBgCg==